package com.ben.microservice.microservicejdbc.jdbcTemplate.rowMapper;


import org.springframework.jdbc.core.RowMapper;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BaseRowMapper<T> implements RowMapper {

    private Class<?> targetClazz;
    private HashMap<String,Field> fieldMap;

    public BaseRowMapper(Class<?> targetClazz){
        this.targetClazz = targetClazz;
        fieldMap = new HashMap<>();
        Field[] fields = targetClazz.getDeclaredFields();
        for (Field field : fields) {
            fieldMap.put(field.getName(),field);
        }
    }

    @Override
    public Object mapRow(ResultSet rs, int arg1) throws SQLException {
        T obj = null;

        try {
            obj = (T)targetClazz.newInstance();
            final ResultSetMetaData metaData = rs.getMetaData();
            int columnLength = metaData.getColumnCount();
            String columnName = null;

            for(int i = 1; i<= columnLength; i++){
                columnName = metaData.getColumnName(i);
                Class fieldClazz = fieldMap.get(camel(columnName)).getType();
                Field field = fieldMap.get(camel(columnName));
                field.setAccessible(true);

                if(fieldClazz == int.class || fieldClazz == Integer.class){
                    field.set(obj,rs.getInt(columnName));
                } else if (fieldClazz == boolean.class || fieldClazz == Boolean.class){
                    field.set(obj,rs.getBoolean(columnName));
                } else if (fieldClazz == String.class){
                    field.set(obj,rs.getString(columnName));
                } else if (fieldClazz == float.class){
                    field.set(obj,rs.getFloat(columnName));
                } else if (fieldClazz == double.class || fieldClazz == Double.class){
                    field.set(obj,rs.getDouble(columnName));
                } else if (fieldClazz == BigDecimal.class){
                    field.set(obj,rs.getBigDecimal(columnName));
                } else if (fieldClazz == short.class || fieldClazz == Short.class){
                    field.set(obj,rs.getShort(columnName));
                } else if (fieldClazz == Timestamp.class){
                    field.set(obj,rs.getTimestamp(columnName));
                } else if (fieldClazz == long.class || fieldClazz == Long.class){
                    field.set(obj,rs.getLong(columnName));
                }
                field.setAccessible(false);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return obj;
    }

    public static String camel(String str){
        Pattern pattern = Pattern.compile("_(\\w)");
        Matcher matcher = pattern.matcher(str);
        StringBuffer sb = new StringBuffer(str);
        if(matcher.find()){
            sb = new StringBuffer();
            matcher.appendReplacement(sb,matcher.group(1).toUpperCase());
            matcher.appendTail(sb);
        } else {
            return sb.toString();
        }

        return camel(sb.toString());
    }
}
